package com.ymt.bpm.service.engine.taskcenter.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.JSONPath;
import com.ymt.bpm.appboot.BpmpProperties;
import com.ymt.bpm.dao.MDao;
import com.ymt.bpm.dao.Mapper;
import com.ymt.bpm.engine.EngineConst;
import com.ymt.bpm.model.*;
import com.ymt.bpm.service.engine.bpd.BpdVersionCacheService;
import com.ymt.bpm.service.engine.taskcenter.PortalProcessService;
import com.ymt.bpm.util.AES;
import com.ymt.bpm.util.Const;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cglib.beans.BeanCopier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * Created by Johnny on 2017/4/12.
 */
@Service
@EnableConfigurationProperties(value = {BpmpProperties.class})
public class PortalProcessServiceImpl implements PortalProcessService {

    private Logger log = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private MDao dao;

    @Autowired
    private BpdVersionCacheService bvcs;

    @Autowired
    private BpmpProperties bpmpProperties;

    @Override
    public JSONArray getFrequentlyBpd(String tenantId, String loginName, int limits) {
        Map<String, Object> paramMap = new HashMap<String, Object>();
        paramMap.put(Const.TENANT_ID, tenantId);
        paramMap.put("userId", loginName);
        paramMap.put("limits", limits);
        List<Map<String, Object>> list = dao.selectList(Mapper.PBpdFavMapper, "selectFrequentlyBpd", paramMap);
        JSONArray rtn = new JSONArray();
        if (list != null && list.size()>0 && list.get(0)!=null) {
            for (Map<String, Object> obj : list) {
                JSONObject json = (JSONObject)JSONObject.toJSON(obj);
                json.put("BPD_ID", AES.encrypt(json.getString("BPD_ID")));
                rtn.add(json);
            }
        }
        return rtn;
    }

    @Override
    public JSONArray getFavouriteBpd(String tenantId, String loginName, int limits) {
        Map<String, Object> paramMap = new HashMap<String, Object>();
        paramMap.put(Const.TENANT_ID, tenantId);
        paramMap.put("userId", loginName);
        paramMap.put("limits", limits);
        List<Map<String, Object>> list = dao.selectList(Mapper.PBpdFavMapper, "selectByUserId", paramMap);
        JSONArray rtn = new JSONArray();
        if (list != null && list.size()>0) {
            for (Map<String, Object> obj : list) {
                JSONObject json = (JSONObject)JSONObject.toJSON(obj);
                json.put("BPD_ID", AES.encrypt(json.getString("BPD_ID")));
                rtn.add(json);
            }
        }
        return rtn;
    }

    @Override
    public JSONArray getTemplates(String tenantId, String loginName, int limits) {
        Map<String, Object> paramMap = new HashMap<String, Object>();
        paramMap.put(Const.TENANT_ID, tenantId);
        paramMap.put("userId", loginName);
        paramMap.put("limits", limits);
        List<Map<String, Object>> list = dao.selectList(Mapper.TaskQueryMapper, "selectTemplates", paramMap);
        JSONArray rtn = new JSONArray();
        if (list != null && list.size()>0) {
            for (Map<String, Object> obj : list) {
                JSONObject json = (JSONObject)JSONObject.toJSON(obj);
                json.put("BPD_ID", AES.encrypt(json.getString("BPD_ID")));
                json.put("TI_ID", AES.encrypt(json.getString("TI_ID")));
                rtn.add(json);
            }
        }
        return rtn;
    }

    @Override
    @Transactional(EngineConst.TRANSACTION_MANAGER)
    public JSONObject addFav(String tenantId, String loginName, String bpdId, String bpdName, int limits) {
        JSONObject rtn = new JSONObject();
        Map<String, Object> paramMap = new HashMap<String, Object>();
        paramMap.put(Const.TENANT_ID, tenantId);
        paramMap.put("userId", loginName);
        int count = dao.selectOne(Mapper.PBpdFavMapper, "countByUserId", paramMap);
        if (count>=limits) {
            rtn.put("limits", count);
            return rtn;
        }
        PBpdFav fav = new PBpdFav();
        if (tenantId!=null && StringUtils.isNumeric(tenantId)) {
            fav.setTenantId(Integer.parseInt(tenantId));
        }
        fav.setBpdId(AES.decrypt(bpdId));
        fav.setBpdName(bpdName);
        fav.setUserId(loginName);
        fav.setSort(count+1);
        int rs = dao.insert(Mapper.PBpdFavMapper, "insert", fav);
        rtn.put(Const.AJAX_RESULT, rs);
        return rtn;
    }

    @Override
    @Transactional(EngineConst.TRANSACTION_MANAGER)
    public JSONObject delFav(String tenantId, String loginName, String bpdId) {
        Map<String, Object> paramMap = new HashMap<String, Object>();
        paramMap.put(Const.TENANT_ID, tenantId);
        paramMap.put("userId", loginName);
        paramMap.put("bpdId", AES.decrypt(bpdId));
        JSONObject rtn = new JSONObject();
        int rs = dao.delete(Mapper.PBpdFavMapper, "delByObj", paramMap);
        rtn.put(Const.AJAX_RESULT, rs);
        return rtn;
    }

    @Override
    public JSONObject getBpdAuthList(String tenantId, String loginName, String authType, String search, int limit) {
        Map<String, Object> paramMap = new HashMap<String, Object>();
        paramMap.put(Const.TENANT_ID, tenantId);
        paramMap.put("userId", loginName);
        paramMap.put("authType", authType);
        paramMap.put("search", search);
        paramMap.put("limit", limit);
        List<Map<String, Object>> list = dao.selectList(Mapper.PBpdCatetreeMapper, "selectBpdAuth", paramMap);

        int total = 0;
        JSONObject rtn = new JSONObject();
        JSONArray rows = new JSONArray();
        if (list!=null && list.size()>0) {
            total =  list.size();
            for (Map<String, Object> map : list) {
                map.put("BPD_ID", AES.encrypt((String)map.get("ID")));
                map.put("BPD_NAME", map.get("NAME"));
                rows.add(JSON.toJSON(map));
            }
        }
        rtn.put("rows", rows);
        rtn.put("total", total);
        return rtn;
    }

    @Override
    public JSONArray getBpdAuthTree(String tenantId, String loginName, String authType) {
        Map<String, Object> paramMap = new HashMap<String, Object>();
        paramMap.put(Const.TENANT_ID, tenantId);
        paramMap.put("userId", loginName);
        paramMap.put("authType", authType);
        List<Map<String, Object>> list = dao.selectList(Mapper.PBpdCatetreeMapper, "selectBpdAuthWithParents", paramMap);
        JSONArray rtn = new JSONArray();
        if (list != null && list.size()>0) {
            for (Map<String, Object> cate : list) {
                JSONObject row = (JSONObject)JSONObject.toJSON(cate);
                if ("1".equals(row.getString("T_TYPE"))) {
                    row.put("ID", AES.encrypt(row.getString("ID")));
                }
                rtn.add(row);
            }
        }
        return rtn;
    }

    @Override
    public JSONObject getBpdSvg(String tenantId, String bpdId, String versionid) {
        Map<String, Object> paramMap = new HashMap<String, Object>();
        paramMap.put(Const.TENANT_ID, tenantId);
        if (log.isDebugEnabled()) {
            log.debug("bpdId encrypt:"+bpdId);
        }
        paramMap.put("bpdId", AES.decrypt(bpdId));
        paramMap.put("versionid", versionid);
        PBpdVersionWithBLOBs version = dao.selectOne(Mapper.PBpdVersionMapper, "selectSvg", paramMap);
        JSONObject rtn = new JSONObject();
        rtn.put("svg", version.getSvg());
        rtn.put("bpmnConfig", version.getBpmnConfig());
        rtn.put("otherConfig", version.getOtherConfig());
        return rtn;
    }

    @Override
    @Transactional(EngineConst.TRANSACTION_MANAGER)
    public JSONObject hasten(String tenantId, String loginName, String displayName, JSONObject params) {
        JSONObject rtn = new JSONObject();
        int rs = 0;
        String msg = params.getString("msg");

        //查询当前任务
        String piId = params.getString("piId");
        Map<String, Object> paramMap = new HashMap<String, Object>();
        paramMap.put(Const.TENANT_ID, tenantId);
        paramMap.put("piId", piId);
        List<Map<String, Object>> todos = dao.selectObjListByObj(Mapper.TaskQueryMapper, "todoUsersByPiId", paramMap);

        //notify instance
        PNotify notify1 = new PNotify();
        if (tenantId!=null && StringUtils.isNumeric(tenantId)) notify1.setTenantId(Integer.parseInt(tenantId));
        notify1.setStatus(PNotify.STATUS_NEW);
        notify1.settType(PNotify.TTYPE_HASTEN);
        notify1.setSender(loginName);
        notify1.setSenderName(displayName);
        BeanCopier copier = BeanCopier.create(PNotify.class, PNotify.class, false);

        if (todos!=null && todos.size()>0) {
            String handleTaskUrlPrefix = bpmpProperties.getSiteUrl() + bpmpProperties.getPrefixHandletask();
            JSONArray notified = new JSONArray();
            JSONArray nowallowed = new JSONArray();
            for (Map<String, Object> todo : todos) {
                String bpdId = (String)todo.get("BPD_ID");
                String bpdName = (String)todo.get("BPD_NAME");
                int versionid = (Integer)todo.get("VERSIONID");
                String activityId = (String)todo.get("ACTIVITY_ID");
                String activityName = (String)todo.get("ACTIVITY_NAME");
                String tiId = (String)todo.get("TI_ID");
                String piEid = (String)todo.get("PI_EID");
                String userId = (String)todo.get("USER_ID");
                String userName = (String)todo.get("USER_NAME");
                JSONObject version = bvcs.getVersionJson(tenantId, bpdId, versionid);
                JSONObject bpmnConfig = version.getJSONObject("bpmnConfig");
                String manualRemind = (String)JSONPath.eval(bpmnConfig, "$."+activityId+".manualRemind");
                if ("1".equals(manualRemind)) {
                    JSONObject allowed = new JSONObject();
                    allowed.put("name", userName+" ("+bpdName+"-"+activityName+")");
                    String manualRemindmethods = (String)JSONPath.eval(bpmnConfig, "$."+activityId+".manualRemindmethods");
                    if (manualRemindmethods!=null && manualRemindmethods.length()>0) {
                        if (manualRemindmethods.toLowerCase().indexOf("msg")>=0) {
                            allowed.put("msg", true);
                            PNotify notify = new PNotify();
                            copier.copy(notify1, notify, null);
                            notify.setId(UUID.randomUUID().toString());
                            notify.setType(PNotify.TYPE_MSG);
                            notify.setPiEid(piEid);
                            notify.setTiId(tiId);
                            notify.setCreateTime((Date)todo.get("CREATE_TIME"));
                            notify.setReceiver(userId);
                            notify.setReceiverName(userName);
                            String content = msg + "<br/><br/>" + bpdName + " - " + activityName;
                            notify.setContent(content);
                            notify.setReadUrl(handleTaskUrlPrefix + tiId);

                            rs += dao.insert("PNotifyMapper", "insert", notify);
                        }
                        if (manualRemindmethods.toLowerCase().indexOf("email")>=0) {
                            allowed.put("email", true);
                            PNotify notify = new PNotify();
                            copier.copy(notify1, notify, null);
                            notify.setId(UUID.randomUUID().toString());
                            notify.setType(PNotify.TYPE_MAIL);
                            notify.setPiEid(piEid);
                            notify.setTiId(tiId);
                            notify.setCreateTime((Date)todo.get("CREATE_TIME"));
                            notify.setReceiver(userId);
                            notify.setReceiverName(userName);
                            String content = msg + "<br/><br/>" + bpdName + " - " + activityName;
                            notify.setContent(content);
                            notify.setReadUrl(handleTaskUrlPrefix + tiId);

                            notify.setDestination((String)todo.get("EMAIL"));
                            rs += dao.insert("PNotifyMapper", "insert", notify);
                        }
                    }
                } else {
                    nowallowed.add(userName+" ("+bpdName+"-"+activityName+")");
                }
            }
            rtn.put("notified", notified);
            rtn.put("nowallowed", nowallowed);
        }
        rtn.put(Const.AJAX_RESULT, rs);
        return rtn;
    }

    @Override
    public JSONObject recall(String tenantId, String loginName, String displayName, String piId) {
        return null;
    }

}
